/*
  <file> main.c </file>
  <brief>
    The main routine calling ulc2xml.
    This file is part of ULS, Unified Lexical Scheme.
  </brief>
  <author>
    Stanley J. Hong <babel96@gmail.com>, 2011.
  </author>
*/

#include "globals.h"
#include "ulc_gram.h"

#include <getopt.h>

char *progname;
int  opt_verbose;
uls_lex_t ulc_lex;
FILE *fout_xml;

static void usage(void)
{
	err_log("%s v1.0", progname);
	err_log("  ULS can be used as front end of yacc/bison");
	err_log("  '%s' demonstrates how ULS is used with yacc/bison", progname);
	err_log("");
	err_log(" Usage:");
	err_log("  %s [-o output-file] <configfile-1>", progname);
	err_log("");
	err_log("  For example,");
	err_log("      %s input1.txt", progname);
	exit(1);
}

static int
globals_init(int argc, char** argv)
{
	progname = uls_filename(argv[0]);
	memset(&ulc_file, 0x00, sizeof(ulc_file_t));
	fout_xml = NULL;
	return 0;
}

static int
parse_options(int argc, char* argv[])
{
	char *outfile_xml = NULL;
	int   opt;

	globals_init(argc, argv);

	while ((opt=getopt(argc, argv, "o:hv")) != -1) {
		switch (opt) {
		case 'o':
			outfile_xml = optarg;
			break;

		case 'h':
			usage();
			break;

		case 'v':
			opt_verbose = 1;
			break;
	
		default:
			err_log("undefined option -%c", opt);
			return -1;
			break;
		}
	}

	if (outfile_xml == NULL) {
		fout_xml = stdout;
	} else if ((fout_xml=fopen(outfile_xml, "w"))==NULL) {
		err_log("can't open output file '%s' for writing", outfile_xml);
		return -1;
	}

	return optind;
}

extern int yyparse(void);
extern YYSTYPE yylval;
static char yy_lexeme_str[32];
char *yytext;
int  yyline;

int
currentline(void)
{
	return yyline;
}

int yylex(void)
{
	char ch;
	int i, tok;

	tok = uls_gettok(&ulc_lex);
	if (tok == TOK_EOI) return 0;

	if (tok == ':' || tok == '\n') {
		if (tok == '\n') ++yyline;
		yy_lexeme_str[0] = tok;
		yy_lexeme_str[1] = '\0';
		yytext = yy_lexeme_str;
		return tok;
	}

	if (tok == TOK_NUM) {
		yytext = uls_lexeme_text(&ulc_lex);
		yylval.i_val = uls_lexeme_int(&ulc_lex);

	} else if (tok==TOK_ID) {
		yytext = strdup(uls_lexeme_text(&ulc_lex));
		yylval.s_val = yytext;

	} else if (tok < 128) {
		yy_lexeme_str[0] = tok;
		for (i=1; i<sizeof(yy_lexeme_str)-1; ) {
			ch = uls_getch(&ulc_lex);
			if (ch == ULS_NEXTCH_NONE || ch == ' ' || ch == '\n') {
				uls_ungetch(&ulc_lex);
				break;
			}
			yy_lexeme_str[i++] = ch;
		}
		yy_lexeme_str[i] = '\0';

		yylval.s_val = yytext = strdup(yy_lexeme_str);
		tok = TOK_WORD;

	} else {
		yytext = uls_lexeme_text(&ulc_lex);
	}

	return tok;
}

int parse_ulc_file(char *file, ulc_file_t *ulc_file)
{
	if (uls_set_file(&ulc_lex, file, 0) < 0) {
		err_log("can't open input-file file %s", file);
		return -1;
	}

	yyline = 1;
	yyparse();

	return 0;
}

int
main(int argc, char* argv[])
{
	char *config_file;
	int i0;

	if ((i0=parse_options(argc, argv)) < 0 || i0 >= argc) {
		usage();
	}

	config_file = argv[i0];

	if (uls_init(&ulc_lex, "ulc.ulc") < 0) {
		err_log("can't init uls-lexer");
		return -1;
	}

	if (opt_verbose) err_log("Processing '%s', ...", config_file);
	parse_ulc_file(config_file, &ulc_file);
	if (opt_verbose) err_log("\tSyntax checking done.");
	uls_deinit(&ulc_lex);

	if (opt_verbose) err_log("Generating output into stdout, ...");
	dump_ulc_file(&ulc_file, fout_xml);
	if (opt_verbose) err_log("\tDone.");

	return 0;
}
